#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/***
 *  测试客户端： ./udp_server.o  172.168.4.254 8081
 *   启动网络调试助手，看是否能够收到数据 
 * 
 * 
 *     ./udp_server.o  192.168.133.133  8080
 */


int main(int argc,char* argv[])
{
    int port; 
    int fd;   // man 2 socket 
    char buf[1024];
    int ret;
    int len; 

if(argc != 3){
    printf(" for example: ./app ip port \r\n");
    return -1;
}
port = atoi(argv[2]);  // man 3 atoi

if(port  < 1025  || port > 65535){
    printf(" port :1025-65535  \r\n");
    return -2;
}

  /****
   *  socket 函数用于打开一个网络连接，成功返回一个网络文件描述符，也是int类型， 以后操作网络连接都通过这个网络描述符   
   *    int socket(int domain, int type, int protocol);
   * 
   *    AF_INET             IPv4 Internet protocols          ip(7)
        AF_INET6            IPv6 Internet protocols          ipv6(7)
   * 
   * domain： 域， 哪类网络ipv4 ipv6...
   *    type : 类型 
   *     SOCK_STREAM ： 表示使用tcp协议，可靠的
   *     SOCK_DGRAM ：  udp的协议， 不可靠的     
   * protocol ： 协议， 0 默认协议  ,  自动选择
   * sockfd = 3  默认 012 已经被使用了
   * 
   */	
   fd=socket(AF_INET,SOCK_DGRAM,0);
  
   if(fd < 0 ){
     printf(" socket  create fail \r\n");
     return  -3;
   }

   struct sockaddr_in local_addr=  {  0  };
   local_addr.sin_family= AF_INET;
   local_addr.sin_port =  htons(port);
  // inet_pton(fd,argv[1],&addr.sin_addr.s_addr);
   local_addr.sin_addr.s_addr  = inet_addr(argv[1]);

   


// udp_server 绑定ip和端口号 
   ret =bind(fd,(struct sockaddr*)&local_addr,sizeof(local_addr));

   

   if (ret <0  )
   {
     printf(" bind fail \r\n");
     return -4;
   }


   struct sockaddr_in src_addr=  {  0  };
   len = sizeof(src_addr);
   memset(buf,0,sizeof(buf));

//192.168.133.133
   while(1){ 
    /** 
     *  成功接收实际字节数
     *    -1 失败，读errno
     */
      ret= recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&src_addr,&len);
      printf("recvfrom->ret = %d\n",ret);
      printf("ip:%s,port:%d\n",inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port));

      //发送给客户端
      ret= sendto(fd,buf, strlen(buf)+1, 0, (struct sockaddr*)&src_addr,sizeof(src_addr) );
      printf("sendto-ret = %d , %s\n",ret,buf);
      memset(buf,0,sizeof(buf));
      
   }

  return 0; 
}
